{
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# Hello LangGraph\n",
        "\n",
        "LangGraph is a library for building stateful, multi-actor applications with LLMs, used to create agent and multi-agent workflows.\n",
        "\n",
        "Compared to other LLM frameworks, it offers these core benefits: cycles, controllability, and persistence.\n",
        "\n",
        "LangGraph allows you to define flows that involve cycles, essential for most agentic architectures, differentiating it from DAG-based solutions.\n",
        "\n",
        "As a very low-level framework, it provides fine-grained control over both the flow and state of your application, crucial for creating reliable agents.\n",
        "\n",
        "Additionally, LangGraph includes built-in persistence, enabling advanced human-in-the-loop and memory features.\n",
        "\n",
        "Key Features¶\n",
        "- **Cycles and Branching:** Implement loops and conditionals in your apps.\n",
        "- **Persistence:** Automatically save state after each step in the graph. Pause and resume the graph execution at any point to support error recovery, human-in-the-loop workflows, time travel and more.\n",
        "- **Human-in-the-Loop:** Interrupt graph execution to approve or edit next action planned by the agent.\n",
        "- **Streaming Support:** Stream outputs as they are produced by each node (including token streaming).\n",
        "- **Integration with LangChain:** LangGraph integrates seamlessly with LangChain and LangSmith (but does not require them).\n",
        "\n",
        "https://langchain-ai.github.io/langgraph/\n",
        "\n",
        "https://chatgpt.com/share/66f9d1bf-58e0-8002-84d0-1c1f8d5b4389"
      ],
      "metadata": {
        "id": "NBDjjf9m2XKN"
      },
      "id": "NBDjjf9m2XKN"
    },
    {
      "cell_type": "markdown",
      "id": "50fa7f8a-8764-4bb9-9968-48b681a0e4f1",
      "metadata": {
        "id": "50fa7f8a-8764-4bb9-9968-48b681a0e4f1"
      },
      "source": [
        "# The Simplest Graph\n",
        "\n",
        "Let's build a simple graph with 2 nodes and simple edges flow.\n",
        "\n",
        "![image.png]()"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 1,
      "id": "ff151ef1-fa30-482a-94da-8f49964afbc3",
      "metadata": {
        "id": "ff151ef1-fa30-482a-94da-8f49964afbc3"
      },
      "outputs": [],
      "source": [
        "%%capture --no-stderr\n",
        "%pip install --quiet -U langgraph"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "5999f8d0-989f-4638-8ade-5c257cbadfe8",
      "metadata": {
        "id": "5999f8d0-989f-4638-8ade-5c257cbadfe8"
      },
      "source": [
        "## State\n",
        "\n",
        "First, define the [State](https://langchain-ai.github.io/langgraph/concepts/low_level/#state) of the graph.\n",
        "\n",
        "The State schema serves as the input schema for all Nodes and Edges in the graph.\n",
        "\n",
        "Let's use the `TypedDict` class from python's `typing` module as our schema, which provides type hints for the keys."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 2,
      "id": "6a90709b-ddfa-4671-8acc-c59969a29991",
      "metadata": {
        "id": "6a90709b-ddfa-4671-8acc-c59969a29991"
      },
      "outputs": [],
      "source": [
        "from typing_extensions import TypedDict\n",
        "\n",
        "class LearningState(TypedDict):\n",
        "    prompt: str"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# prompt: create an example from above LearningState\n",
        "lahore_state: LearningState = LearningState(prompt= \"hello from UMT Lahore\")\n"
      ],
      "metadata": {
        "id": "daLx0ePEvDaS"
      },
      "id": "daLx0ePEvDaS",
      "execution_count": 3,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "print(lahore_state)\n",
        "print(lahore_state['prompt'])\n",
        "print(lahore_state['prompt'] +\" I am\")\n",
        "print(lahore_state)\n",
        "print(type(lahore_state))"
      ],
      "metadata": {
        "id": "ZnKfFYtwvn0K",
        "outputId": "0e72d926-bee4-466f-b009-0d5549c93c03",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "id": "ZnKfFYtwvn0K",
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "{'prompt': 'hello from UMT Lahore'}\n",
            "hello from UMT Lahore\n",
            "hello from UMT Lahore I am\n",
            "{'prompt': 'hello from UMT Lahore'}\n",
            "<class 'dict'>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "markdown",
      "id": "888509e1-cbde-4c03-99a0-2560dd2e262d",
      "metadata": {
        "id": "888509e1-cbde-4c03-99a0-2560dd2e262d"
      },
      "source": [
        "## Nodes\n",
        "\n",
        "[Nodes](https://langchain-ai.github.io/langgraph/concepts/low_level/#nodes) are just python functions.\n",
        "\n",
        "The first positional argument is the state, as defined above.\n",
        "\n",
        "Because the state is a `TypedDict` with schema as defined above, each node can access the key, `graph_state`, with `state['graph_state']`.\n",
        "\n",
        "Each node returns a new value of the state key `graph_state`.\n",
        "  \n",
        "By default, the new value returned by each node [will override](https://langchain-ai.github.io/langgraph/concepts/low_level/#reducers) the prior state value."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "id": "e8aabcb7-494c-4d35-be08-f81c76d75a6b",
      "metadata": {
        "id": "e8aabcb7-494c-4d35-be08-f81c76d75a6b"
      },
      "outputs": [],
      "source": [
        "def node_1(state: LearningState) -> LearningState:\n",
        "    print(\"---Node 1 State---\", state)\n",
        "    return {\"prompt\": state['prompt'] +\" I am\"}\n",
        "\n",
        "def node_2(state: LearningState) -> LearningState:\n",
        "    print(\"---Node 2 State---\", state)\n",
        "    return {\"prompt\": state['prompt'] +\" happy!\"}"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "ad056608-8c8f-4999-bb53-10583efa4ed8",
      "metadata": {
        "id": "ad056608-8c8f-4999-bb53-10583efa4ed8"
      },
      "source": [
        "## Edges\n",
        "\n",
        "[Edges](https://langchain-ai.github.io/langgraph/concepts/low_level/#edges) connect the nodes.\n",
        "\n",
        "Normal Edges are used if you want to *always* go from, for example, `node_1` to `node_2`."
      ]
    },
    {
      "cell_type": "markdown",
      "id": "9282ea7a-5ed2-4641-bed8-c3472d54c951",
      "metadata": {
        "id": "9282ea7a-5ed2-4641-bed8-c3472d54c951"
      },
      "source": [
        "## Graph Construction\n",
        "\n",
        "Now, we build the graph from our [components](\n",
        "https://langchain-ai.github.io/langgraph/concepts/low_level/) defined above.\n",
        "\n",
        "The [StateGraph class](https://langchain-ai.github.io/langgraph/concepts/low_level/#stategraph) is the graph class that we can use.\n",
        "\n",
        "First, we initialize a StateGraph with the `State` class we defined above.\n",
        "\n",
        "Then, we add our nodes and edges.\n",
        "\n",
        "We use the [`START` Node, a special node](https://langchain-ai.github.io/langgraph/concepts/low_level/#start-node) that sends user input to the graph, to indicate where to start our graph.\n",
        "\n",
        "The [`END` Node](https://langchain-ai.github.io/langgraph/concepts/low_level/#end-node) is a special node that represents a terminal node.\n",
        "\n",
        "Finally, we [compile our graph](https://langchain-ai.github.io/langgraph/concepts/low_level/#compiling-your-graph) to perform a few basic checks on the graph structure.\n",
        "\n",
        "We can visualize the graph as a [Mermaid diagram](https://github.com/mermaid-js/mermaid)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 6,
      "id": "7deb0359-55c1-4545-b52e-8252994befbb",
      "metadata": {
        "id": "7deb0359-55c1-4545-b52e-8252994befbb"
      },
      "outputs": [],
      "source": [
        "from IPython.display import Image, display # Preview Graph\n",
        "\n",
        "from langgraph.graph import StateGraph, START, END\n",
        "from langgraph.graph.state import CompiledStateGraph # type\n",
        "\n",
        "# Build graph\n",
        "builder: StateGraph = StateGraph(state_schema=LearningState)\n"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(type(builder))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "rQhxbkwYHEkm",
        "outputId": "4381db2f-bb3f-4f2f-ec87-7e99ba965fc6"
      },
      "id": "rQhxbkwYHEkm",
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<class 'langgraph.graph.state.StateGraph'>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Nodes\n",
        "builder.add_node(\"node_1\", node_1)\n",
        "builder.add_node(\"node_2\", node_2)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "gLi7y5YxHHvo",
        "outputId": "a5f7a1ed-325d-455c-e599-58429f653596"
      },
      "id": "gLi7y5YxHHvo",
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<langgraph.graph.state.StateGraph at 0x79a50ad2e8f0>"
            ]
          },
          "metadata": {},
          "execution_count": 8
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Simples Edges Logic\n",
        "builder.add_edge(START, \"node_1\")\n",
        "builder.add_edge(\"node_1\", \"node_2\")\n",
        "builder.add_edge(\"node_2\", END)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ghVXhjr4HKzM",
        "outputId": "5f47c254-5808-455e-dd91-51ba57c2f84e"
      },
      "id": "ghVXhjr4HKzM",
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<langgraph.graph.state.StateGraph at 0x79a50ad2e8f0>"
            ]
          },
          "metadata": {},
          "execution_count": 9
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Add\n",
        "graph: CompiledStateGraph = builder.compile()"
      ],
      "metadata": {
        "id": "3sfU5J2_HRyx"
      },
      "id": "3sfU5J2_HRyx",
      "execution_count": 10,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "print(graph)"
      ],
      "metadata": {
        "id": "rTFDoO-nxxP-",
        "outputId": "141b8490-e245-4089-bad0-f00ef2f77303",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "id": "rTFDoO-nxxP-",
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "<langgraph.graph.state.CompiledStateGraph object at 0x79a4e5d20280>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(graph.get_graph())"
      ],
      "metadata": {
        "id": "XLba0cdax4HJ",
        "outputId": "a7835307-5853-4a37-a413-bb2322c83120",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "id": "XLba0cdax4HJ",
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Graph(nodes={'__start__': Node(id='__start__', name='__start__', data=<class 'langchain_core.utils.pydantic.LangGraphInput'>, metadata=None), 'node_1': Node(id='node_1', name='node_1', data=node_1(tags=None, recurse=True, func_accepts_config=False, func_accepts={'writer': False}), metadata=None), 'node_2': Node(id='node_2', name='node_2', data=node_2(tags=None, recurse=True, func_accepts_config=False, func_accepts={'writer': False}), metadata=None), '__end__': Node(id='__end__', name='__end__', data=<class 'langchain_core.utils.pydantic.LangGraphOutput'>, metadata=None)}, edges=[Edge(source='__start__', target='node_1', data=None, conditional=False), Edge(source='node_1', target='node_2', data=None, conditional=False), Edge(source='node_2', target='__end__', data=None, conditional=False)])\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# View\n",
        "display(Image(graph.get_graph().draw_mermaid_png()))"
      ],
      "metadata": {
        "id": "_3js4e8pxzwR",
        "outputId": "1196a64f-46b4-4a95-8f8c-b9e82334bce2",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 350
        }
      },
      "id": "_3js4e8pxzwR",
      "execution_count": 13,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/jpeg": "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\n",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "markdown",
      "id": "00617c74-2647-44ea-8a2e-310dd96c0d26",
      "metadata": {
        "id": "00617c74-2647-44ea-8a2e-310dd96c0d26"
      },
      "source": [
        "## Graph Invocation\n",
        "\n",
        "The compiled graph implements the [runnable](https://python.langchain.com/v0.1/docs/expression_language/interface/) protocol.\n",
        "\n",
        "This provides a standard way to execute LangChain components.\n",
        "\n",
        "`invoke` is one of the standard methods in this interface.\n",
        "\n",
        "The input is a dictionary `{\"graph_state\": \"Hi, this is lance.\"}`, which sets the initial value for our graph state dict.\n",
        "\n",
        "When `invoke` is called, the graph starts execution from the `START` node.\n",
        "\n",
        "It progresses through the defined nodes (`node_1`, `node_2`, `node_3`) in order.\n",
        "\n",
        "Each node function receives the current state and returns a new value, which overrides the graph state.\n",
        "\n",
        "The execution continues until it reaches the `END` node."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "id": "e895f17a-e835-4e8a-8e1b-63fe6d27cc52",
      "metadata": {
        "id": "e895f17a-e835-4e8a-8e1b-63fe6d27cc52",
        "outputId": "4063a81f-d7e5-4a8f-c0a3-cfb172aa3ee4",
        "colab": {
          "base_uri": "https://localhost:8080/"
        }
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "---Node 1 State--- {'prompt': 'Hi'}\n",
            "---Node 2 State--- {'prompt': 'Hi I am'}\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "{'prompt': 'Hi I am happy!'}"
            ]
          },
          "metadata": {},
          "execution_count": 14
        }
      ],
      "source": [
        "graph.invoke({\"prompt\" : \"Hi\"})"
      ]
    },
    {
      "cell_type": "markdown",
      "id": "082399c3-18bd-4b67-97c1-2005f268abc5",
      "metadata": {
        "id": "082399c3-18bd-4b67-97c1-2005f268abc5"
      },
      "source": [
        "`invoke` runs the entire graph synchronously.\n",
        "\n",
        "This waits for each step to complete before moving to the next.\n",
        "\n",
        "It returns the final state of the graph after all nodes have executed.\n",
        "\n",
        "In this case, it returns the state after `node_3` has completed:\n",
        "\n",
        "```\n",
        "{'graph_state': 'Hi, this is Lance. I am sad!'}\n",
        "```"
      ]
    },
    {
      "cell_type": "markdown",
      "source": [
        "## Task: In Nodes Use LLM == GoogleChatModel in Langchain"
      ],
      "metadata": {
        "id": "ksPUpAjpHt0w"
      },
      "id": "ksPUpAjpHt0w"
    },
    {
      "cell_type": "code",
      "source": [
        "%pip install -q -U langchain\n",
        "%pip install -q -U langchain-google-genai\n"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "hY07Hxm6H-Y4",
        "outputId": "75eafe4c-8809-444d-b2a5-44196f06bbc3"
      },
      "id": "hY07Hxm6H-Y4",
      "execution_count": 15,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\u001b[2K   \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.0/1.0 MB\u001b[0m \u001b[31m4.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
            "\u001b[?25h"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from google.colab import userdata\n",
        "google_api_key = userdata.get('GEMINI_API_KEY')\n"
      ],
      "metadata": {
        "id": "Aub5NIxCIXRq"
      },
      "id": "Aub5NIxCIXRq",
      "execution_count": 16,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "print(google_api_key)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "puSGfqxRI2Hc",
        "outputId": "216fe402-0b6e-4281-ce65-f3ae77de87a6"
      },
      "id": "puSGfqxRI2Hc",
      "execution_count": 17,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "AIzaSyDeOXv5e7ZNX_EL4uV9pSs-95Q4Cy1-Irc\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from langchain_google_genai import ChatGoogleGenerativeAI\n",
        "\n",
        "# Initialize an instance of the ChatGoogleGenerativeAI with specific parameters\n",
        "llm: ChatGoogleGenerativeAI = ChatGoogleGenerativeAI(\n",
        "    model=\"gemini-1.5-flash\",  # Specify the model to use\n",
        "    api_key=google_api_key,     # Provide the Google API key for authentication\n",
        ")"
      ],
      "metadata": {
        "id": "ThGHbMSxIeDb"
      },
      "id": "ThGHbMSxIeDb",
      "execution_count": 18,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# Import the AIMessage class currently will be used for typing\n",
        "from langchain_core.messages.ai import AIMessage\n",
        "\n",
        "ai_msg: AIMessage = llm.invoke(\"Hi?\")"
      ],
      "metadata": {
        "id": "26FM9Xb3JFs9"
      },
      "id": "26FM9Xb3JFs9",
      "execution_count": 19,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "print(ai_msg.content)\n",
        "print(type(ai_msg.content))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "xpjcKudbJMd2",
        "outputId": "8fc65e0c-b230-4e5a-d068-b837d3ad2c16"
      },
      "id": "xpjcKudbJMd2",
      "execution_count": 20,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "Hi! How can I help you today? \n",
            "\n",
            "<class 'str'>\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from typing_extensions import TypedDict\n",
        "\n",
        "class FirstLLMAgentCall(TypedDict):\n",
        "    prompt: str\n",
        "    output: str"
      ],
      "metadata": {
        "id": "rGJm93X6JmBw"
      },
      "id": "rGJm93X6JmBw",
      "execution_count": 21,
      "outputs": []
    },
    {
      "cell_type": "code",
      "execution_count": 22,
      "id": "db16ab8d-b817-4f3a-befc-a02b579c4fca",
      "metadata": {
        "id": "db16ab8d-b817-4f3a-befc-a02b579c4fca"
      },
      "outputs": [],
      "source": [
        "def node_1(state: FirstLLMAgentCall):\n",
        "    print(\"---Node 1---\", state)\n",
        "    prompt = state[\"prompt\"]\n",
        "    ai_msg: AIMessage = llm.invoke(prompt)\n",
        "    return {\"output\": ai_msg.content}"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "zeeshan_bhai_greet_message = node_1(FirstLLMAgentCall(prompt=\"Hello from UMT\"))\n",
        "print(zeeshan_bhai_greet_message)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ZQLLIhCzKoA-",
        "outputId": "82c98fe7-65c5-498f-8877-7fd5399a5c88"
      },
      "id": "ZQLLIhCzKoA-",
      "execution_count": 23,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "---Node 1--- {'prompt': 'Hello from UMT'}\n",
            "{'output': \"Hello from UMT! \\n\\nIt's nice to hear from you. What can I do for you today? \\n\"}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "from IPython.display import Image, display # Preview Graph\n",
        "\n",
        "from langgraph.graph import StateGraph, START, END\n",
        "from langgraph.graph.state import CompiledStateGraph # type\n",
        "\n",
        "# Build graph\n",
        "builder: StateGraph = StateGraph(state_schema=FirstLLMAgentCall)\n",
        "\n",
        "# Define Nodes\n",
        "builder.add_node(\"node_1\", node_1)\n",
        "\n",
        "# Add Edges\n",
        "builder.add_edge(START, \"node_1\")\n",
        "builder.add_edge(\"node_1\", END)\n",
        "\n",
        "# Compile Graph\n",
        "graph: CompiledStateGraph = builder.compile()"
      ],
      "metadata": {
        "id": "iYkxVcSILu1E"
      },
      "id": "iYkxVcSILu1E",
      "execution_count": 24,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "# View\n",
        "display(Image(graph.get_graph().draw_mermaid_png()))"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 251
        },
        "id": "zsJfH1KcMA6d",
        "outputId": "5580c194-47cb-4e77-f6ff-80270dcab884"
      },
      "id": "zsJfH1KcMA6d",
      "execution_count": 25,
      "outputs": [
        {
          "output_type": "display_data",
          "data": {
            "image/jpeg": "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\n",
            "text/plain": [
              "<IPython.core.display.Image object>"
            ]
          },
          "metadata": {}
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "result = graph.invoke({\"prompt\" : \"Motivate me to learn LangGraph\"})"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "N1-sVdlZMCs7",
        "outputId": "83b21dad-df1a-4972-d927-66b132e9405e"
      },
      "id": "N1-sVdlZMCs7",
      "execution_count": 28,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "---Node 1--- {'prompt': 'Motivate me to learn LangGraph'}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "print(result)"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "Q0frgti85_Qf",
        "outputId": "c0474244-8234-42fe-e8f2-4ba7606f2806"
      },
      "id": "Q0frgti85_Qf",
      "execution_count": 29,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "{'prompt': 'Motivate me to learn LangGraph', 'output': \"## Reasons to Learn LangGraph:\\n\\n**1. Power Up Your Natural Language Processing (NLP):** LangGraph offers a powerful and versatile tool for working with text data. It allows you to represent text as graphs, enabling you to:\\n\\n* **Uncover hidden relationships and patterns:** Go beyond simple keyword matching and analyze text in a more nuanced way.\\n* **Build robust NLP applications:** Leverage the graph structure for tasks like sentiment analysis, topic modeling, and question answering.\\n* **Improve accuracy and efficiency:** Benefit from LangGraph's optimized algorithms and libraries for faster and more accurate results.\\n\\n**2. Open Up New Opportunities:** LangGraph is gaining popularity in the NLP community, creating exciting opportunities for:\\n\\n* **Career advancement:**  Demonstrate your expertise in a cutting-edge technology and stand out in the job market.\\n* **Research and development:** Contribute to advancements in NLP and other fields by utilizing LangGraph's capabilities.\\n* **Innovation:** Develop novel NLP applications and solutions that leverage the unique features of LangGraph.\\n\\n**3. Enjoy the Learning Process:** LangGraph offers:\\n\\n* **A vibrant and active community:** Connect with other LangGraph enthusiasts and learn from their experience.\\n* **Comprehensive documentation and resources:** Get started easily with clear tutorials and guides.\\n* **A rewarding journey:** Discover the power of graph-based NLP and witness the impact of your learning on your projects.\\n\\n**4. Make a Difference:** LangGraph can be used to address real-world challenges in various domains:\\n\\n* **Healthcare:** Analyze medical text to improve diagnosis and treatment.\\n* **Finance:** Detect fraud and identify investment opportunities by analyzing financial documents.\\n* **Social Sciences:** Understand public sentiment and social trends from online data.\\n\\n**In summary, learning LangGraph empowers you with a powerful tool for NLP, opens up new opportunities, and provides a rewarding and impactful learning experience.**\\n\\n**Are you ready to unlock the potential of LangGraph?** \\n\"}\n"
          ]
        }
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# just another helpter function\n",
        "import textwrap\n",
        "from IPython.display import display, Markdown\n",
        "\n",
        "def to_markdown(text)-> Markdown:\n",
        "    text : str = text.replace(\"•\", \"  *\")\n",
        "    return Markdown(textwrap.indent(text, \"> \", predicate=lambda _: True))"
      ],
      "metadata": {
        "id": "fxf4zVmk5uRP"
      },
      "id": "fxf4zVmk5uRP",
      "execution_count": 32,
      "outputs": []
    },
    {
      "cell_type": "code",
      "source": [
        "print(\"PROMPT: \", result['prompt'])\n",
        "to_markdown(result['output'])"
      ],
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 534
        },
        "id": "ZNAiFSiU6Cr7",
        "outputId": "1b5ec64c-abdf-4eeb-f019-d215c2cfe296"
      },
      "id": "ZNAiFSiU6Cr7",
      "execution_count": 34,
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "PROMPT:  Motivate me to learn LangGraph\n"
          ]
        },
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ],
            "text/markdown": "> ## Reasons to Learn LangGraph:\n> \n> **1. Power Up Your Natural Language Processing (NLP):** LangGraph offers a powerful and versatile tool for working with text data. It allows you to represent text as graphs, enabling you to:\n> \n> * **Uncover hidden relationships and patterns:** Go beyond simple keyword matching and analyze text in a more nuanced way.\n> * **Build robust NLP applications:** Leverage the graph structure for tasks like sentiment analysis, topic modeling, and question answering.\n> * **Improve accuracy and efficiency:** Benefit from LangGraph's optimized algorithms and libraries for faster and more accurate results.\n> \n> **2. Open Up New Opportunities:** LangGraph is gaining popularity in the NLP community, creating exciting opportunities for:\n> \n> * **Career advancement:**  Demonstrate your expertise in a cutting-edge technology and stand out in the job market.\n> * **Research and development:** Contribute to advancements in NLP and other fields by utilizing LangGraph's capabilities.\n> * **Innovation:** Develop novel NLP applications and solutions that leverage the unique features of LangGraph.\n> \n> **3. Enjoy the Learning Process:** LangGraph offers:\n> \n> * **A vibrant and active community:** Connect with other LangGraph enthusiasts and learn from their experience.\n> * **Comprehensive documentation and resources:** Get started easily with clear tutorials and guides.\n> * **A rewarding journey:** Discover the power of graph-based NLP and witness the impact of your learning on your projects.\n> \n> **4. Make a Difference:** LangGraph can be used to address real-world challenges in various domains:\n> \n> * **Healthcare:** Analyze medical text to improve diagnosis and treatment.\n> * **Finance:** Detect fraud and identify investment opportunities by analyzing financial documents.\n> * **Social Sciences:** Understand public sentiment and social trends from online data.\n> \n> **In summary, learning LangGraph empowers you with a powerful tool for NLP, opens up new opportunities, and provides a rewarding and impactful learning experience.**\n> \n> **Are you ready to unlock the potential of LangGraph?** \n"
          },
          "metadata": {},
          "execution_count": 34
        }
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3 (ipykernel)",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.12.6"
    },
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 5
}